function selector(select, Aparent) {
  let parent = Aparent || document
  let realSelector
  if (select.indexOf('#') !== -1) {
    realSelector = select.slice(1)
    return parent.getElementById(realSelector)
  } else if (select.indexOf('.') !== -1) {
    realSelector = select.slice(1)
    return parent.querySelectorAll(realSelector)
  } else {
    return parent.getElementsByTagName(select)
  }
}
const canvas = selector('#canvas')
const ctx = canvas.getContext('2d')
ctx.globalCompositeOperation = 'source-atop'

const RATIO = 2

const tool = selector('#tool')
const toolHeight = tool.offsetHeight
let canvasOffset = canvas.getBoundingClientRect()
const canvasWidth = canvas.width = canvasOffset.width * RATIO
const canvasHeight = canvas.height = (canvasOffset.height - toolHeight) * RATIO
canvas.style.height = canvasHeight / RATIO + 'px'
canvasOffset = canvas.getBoundingClientRect()

let lastImageData = []

// 坐标转换 相对窗口坐标变为canvas实际坐标
function windowToCanvas(x, y) {
  return {
    x: (x - canvasOffset.left) * (canvasWidth / canvasOffset.width),
    y: (y - canvasOffset.top) * (canvasHeight / canvasOffset.height)
  }
}

// 获取鼠标canvas坐标
function getTouchPosition(e) {
  let touch = e.changedTouches[0]
  return windowToCanvas(touch.clientX, touch.clientY)
}
// 鼠标点击canvas坐标的对称点坐标
function getTouchPositionD(e) {
  let touch = e.changedTouches[0]
  var zb = windowToCanvas(touch.clientX, touch.clientY)
  return {
    x: canvasWidth - zb.x,
    y: zb.y
  }
}

// 储存画布信息（用于撤回）
function saveImageData(data) {
  (lastImageData.length == 5) && (lastImageData.shift())
  lastImageData.push(data)
}

// 工具基础 宽度，颜色，是否在绘画中，是否被选中
class Basic {
  constructor(width = RATIO, color = '#000') {
    this.width = width
    this.color = color
    this.drawing = false
    this.isSelect = false
  }
}

//铅笔类 通过简单的路径描点连线
class Pencil extends Basic {
  constructor(width = RATIO, color = '#000') {
    super(width, color)
    this.name = 'pencil'
    this.dom = selector(`#${this.name}`)
  }
  begin(loc) {
    saveImageData(ctx.getImageData(0, 0, canvasWidth, canvasHeight))
    // 先保存画布状态，再改变画布状态
    ctx.save()
    ctx.lineWidth = this.width
    ctx.strokeStyle = this.color
    ctx.beginPath()
    ctx.moveTo(loc.x + 0.5, loc.y + 0.5)
  }
  draw(loc) {
    ctx.lineTo(loc.x + 0.5, loc.y + 0.5)
    ctx.stroke()
  }
  end(loc) {
    ctx.lineTo(loc.x + 0.5, loc.y + 0.5)
    ctx.stroke()
    // 恢复到之前的画布状态
    ctx.restore()
  }
  bindEvent() {
    canvas.addEventListener('touchstart', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      this.drawing = true
      let loc = getTouchPosition(e)
      this.begin(loc)
    })
    canvas.addEventListener('touchmove', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      if (this.drawing) {
        let loc = getTouchPosition(e)
        this.draw(loc)
      }
    })
    canvas.addEventListener('touchend', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      let loc = getTouchPosition(e)
      this.end(loc)
      this.drawing = false
    })
  }
}

// 橡皮 颜色为背景色的铅笔，但是在对称变换的时候会有问题，以后会改成用clearRect来擦除
class Eraser extends Pencil {
  constructor(width) {
    super(width, '#fff')
    this.name = 'eraser'
    this.dom = selector(`#${this.name}`)
  }
}

// 清空
class Clear extends Basic {
  constructor(width) {
    super(width, '#fff')
    this.name = 'clr'
    this.dom = selector(`#${this.name}`)
  }
  bindEvent() {
  }
}

// 线段类 拖动开始时先储存画布当前数据，之后每次拖动，先把画布数据铺上，再化线段
class Line extends Basic {
  constructor(width = RATIO, color = '#000') {
    super(width, color)
    this.startPosition = {
      x: 0,
      y: 0
    }
    this.firstDot = ctx.getImageData(0, 0, canvasWidth, canvasHeight)
    this.name = 'line'
    this.dom = selector(`#${this.name}`)
  }
  begin(loc) {
    // 获取当前画布数据
    this.firstDot = ctx.getImageData(0, 0, canvasWidth, canvasHeight)
    saveImageData(this.firstDot)
    Object.assign(this.startPosition, loc)
    ctx.save()
    ctx.lineWidth = this.width
    ctx.strokeStyle = this.color
  }
  draw(loc) {
    // 铺上拖动开始时的画布数据，并绘制一条线段，之后每次触发都会县覆盖掉已绘制的线段，再绘制新线段
    ctx.putImageData(this.firstDot, 0, 0)
    ctx.beginPath()
    ctx.moveTo(this.startPosition.x, this.startPosition.y)
    ctx.lineTo(loc.x, loc.y)
    ctx.stroke()
  }
  end(loc) {
    ctx.putImageData(this.firstDot, 0, 0)
    ctx.beginPath()
    ctx.moveTo(this.startPosition.x, this.startPosition.y)
    ctx.lineTo(loc.x, loc.y)
    ctx.stroke()
    ctx.restore()
  }
  bindEvent() {
    canvas.addEventListener('touchstart', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      this.drawing = true
      let loc = getTouchPosition(e)
      this.begin(loc)
    })
    canvas.addEventListener('touchmove', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      if (this.drawing) {
        let loc = getTouchPosition(e)
        this.draw(loc)
      }
    })
    canvas.addEventListener('touchend', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      let loc = getTouchPosition(e)
      this.end(loc)
      this.drawing = false
    })
  }
}

// 方形 记录初始坐标，根据鼠标坐标画正方形，和线段类似
class Rect extends Basic {
  constructor(width = RATIO, color = '#000') {
    super(width, color)
    this.startPosition = {
      x: 0,
      y: 0
    }
    this.firstDot = ctx.getImageData(0, 0, canvasWidth, canvasHeight)
    this.name = 'rect'
    this.dom = selector(`#${this.name}`)
  }
  begin(loc) {
    this.firstDot = ctx.getImageData(0, 0, canvasWidth, canvasHeight)
    saveImageData(this.firstDot)
    Object.assign(this.startPosition, loc)
    ctx.save()
    ctx.lineWidth = this.width
    ctx.strokeStyle = this.color
  }
  draw(loc) {
    ctx.putImageData(this.firstDot, 0, 0)
    const rect = {
      x: this.startPosition.x <= loc.x ? this.startPosition.x : loc.x,
      y: this.startPosition.y <= loc.y ? this.startPosition.y : loc.y,
      width: Math.abs(this.startPosition.x - loc.x),
      height: Math.abs(this.startPosition.y - loc.y)
    }
    ctx.beginPath()
    ctx.rect(rect.x, rect.y, rect.width, rect.height)
    ctx.stroke()
  }
  end(loc) {
    ctx.putImageData(this.firstDot, 0, 0)
    const rect = {
      x: this.startPosition.x <= loc.x ? this.startPosition.x : loc.x,
      y: this.startPosition.y <= loc.y ? this.startPosition.y : loc.y,
      width: Math.abs(this.startPosition.x - loc.x),
      height: Math.abs(this.startPosition.y - loc.y)
    }
    ctx.beginPath()
    ctx.rect(rect.x, rect.y, rect.width, rect.height)
    ctx.stroke()
    ctx.restore()
  }
  bindEvent() {
    canvas.addEventListener('touchstart', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      this.drawing = true
      let loc = getTouchPosition(e)
      this.begin(loc)
    })
    canvas.addEventListener('touchmove', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      if (this.drawing) {
        let loc = getTouchPosition(e)
        this.draw(loc)
      }
    })
    canvas.addEventListener('touchend', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      let loc = getTouchPosition(e)
      this.end(loc)
      this.drawing = false
    })
  }
}

// 圆形 均匀压缩法 根据起始坐标和结束坐标找一个方形，方形的长边作为圆的半径 画以长边为边的正方形的内切圆 再根据长边与窄边的比例，压缩为原方形的内切椭圆
class Round extends Basic {
  constructor(width = RATIO, color = '#000') {
    super(width, color)
    this.startPosition = {
      x: 0,
      y: 0
    }
    this.firstDot = ctx.getImageData(0, 0, canvasWidth, canvasHeight)
    this.name = 'round'
    this.dom = selector(`#${this.name}`)
  }
  drawCalculate(loc) {
    ctx.save()
    ctx.lineWidth = this.width
    ctx.strokeStyle = this.color
    ctx.putImageData(this.firstDot, 0, 0)
    const rect = {
      width: loc.x - this.startPosition.x,
      height: loc.y - this.startPosition.y
    }
    const rMax = Math.max(Math.abs(rect.width), Math.abs(rect.height))
    rect.x = this.startPosition.x + rect.width / 2
    rect.y = this.startPosition.y + rect.height / 2
    rect.scale = {
      x: Math.abs(rect.width) / rMax,
      y: Math.abs(rect.height) / rMax
    }
    ctx.scale(rect.scale.x, rect.scale.y)
    ctx.beginPath()
    ctx.arc(rect.x / rect.scale.x, rect.y / rect.scale.y, rMax / 2, 0, Math.PI * 2)
    ctx.stroke()
    ctx.restore()
  }
  begin(loc) {
    this.firstDot = ctx.getImageData(0, 0, canvasWidth, canvasHeight)
    saveImageData(this.firstDot)
    Object.assign(this.startPosition, loc)
  }
  draw(loc) {
    this.drawCalculate(loc)
  }
  end(loc) {
    this.drawCalculate(loc)
  }
  bindEvent() {
    canvas.addEventListener('touchstart', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      this.drawing = true
      let loc = getTouchPosition(e)
      this.begin(loc)
    })
    canvas.addEventListener('touchmove', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      if (this.drawing) {
        let loc = getTouchPosition(e)
        this.draw(loc)
      }
    })
    canvas.addEventListener('touchend', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      let loc = getTouchPosition(e)
      this.end(loc)
      this.drawing = false
    })
  }
}

// 左右对称
class Zuoyou extends Basic {
  constructor(width = RATIO, color = '#000') {
    super(width, color)
    this.name = 'zuoyou'
    this.dom = selector(`#${this.name}`)
  }
  begin() {
    saveImageData(ctx.getImageData(0, 0, canvasWidth, canvasHeight))
    // 先保存画布状态，再改变画布状态
    ctx.save()
    ctx.lineWidth = this.width
    ctx.strokeStyle = this.color
    ctx.beginPath()
  }
  draw2(loc) {
    ctx.moveTo(loc.bx, loc.by)
    ctx.lineTo(loc.ex, loc.ey)
    loc.bx = loc.ex
    loc.by = loc.ey
    ctx.stroke()
  }
  bindEvent() {
    var dot = [
      // 鼠标点
      {
        bx: 0,
        by: 0,
        ex: 0,
        ey: 0,
      },
      // 对称点
      {
        bx: 0,
        by: 0,
        ex: 0,
        ey: 0,
      }
    ]
    canvas.addEventListener('touchstart', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      this.drawing = true

      this.begin()

      let loc = getTouchPosition(e)
      let dloc = getTouchPositionD(e)
      dot[0].bx = loc.x
      dot[0].by = loc.y
      dot[1].bx = dloc.x
      dot[1].by = dloc.y
    })
    canvas.addEventListener('touchmove', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      if (this.drawing) {
        let loc = getTouchPosition(e)
        let dloc = getTouchPositionD(e)
        dot[0].ex = loc.x
        dot[0].ey = loc.y
        dot[1].ex = dloc.x
        dot[1].ey = dloc.y
        this.draw2(dot[0])
        this.draw2(dot[1])
      }
    })
  }
}

// 中心对称
class Xuanzhuan extends Basic {
  //  问题线条  7 11  13  14  16  17
  constructor(width = RATIO, color = '#000') {
    super(width, color)
    this.name = 'xuanzhuan'
    this.dom = selector(`#${this.name}`)
  }
  getNum() {
    var num = 6;
    var sel = document.getElementById("zxdc"); //定位id
    var index = sel.selectedIndex; // 选中索引
    var num = sel.options[index].value; // 选中值
    return num
  }


  begin() {
    saveImageData(ctx.getImageData(0, 0, canvasWidth, canvasHeight))
    // 先保存画布状态，再改变画布状态
    ctx.save()
    ctx.lineWidth = this.width
    ctx.strokeStyle = this.color
    ctx.beginPath()
  }

  drawFn(op, num) {
    var deg = Math.floor(360 / num);
    var that = this
    for (var i = 0, l = 360; i < l; i += deg) {
      this.drawRotate(i / 180 * Math.PI, function (ctx) {
        that.draw(op);
      });
    }
  }
  drawRotate(deg, fn, _ctx) {
    _ctx = _ctx || ctx
    _ctx.save();
    _ctx.translate(canvas.width / 2, canvas.height / 2);
    _ctx.rotate(deg);
    fn && fn(_ctx);
    _ctx.restore();
  }
  draw(option, _ctx) {
    _ctx = _ctx || ctx;
    _ctx.beginPath();
    _ctx.moveTo(option.bx - canvas.width / 2, option.by - canvas.height / 2);
    _ctx.lineTo(option.ex - canvas.width / 2, option.ey - canvas.height / 2);
    _ctx.stroke();
  }

  bindEvent() {

    var num = this.getNum()

    var sel = document.getElementById("zxdc")
    var that = this
    sel.onchange = function () {
      num = that.getNum()
    }

    var dot = [
      // 鼠标点
      {
        bx: 0,
        by: 0,
        ex: 0,
        ey: 0,
      }
    ]

    canvas.addEventListener('touchstart', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      this.begin()
      this.drawing = true
      let loc = getTouchPosition(e)
      dot[0].ex = dot[0].bx = loc.x
      dot[0].ey = dot[0].by = loc.y
    })
    canvas.addEventListener('touchmove', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      if (this.drawing) {
        let loc = getTouchPosition(e)
        let dloc = getTouchPositionD(e)
        dot[0].bx = dot[0].ex
        dot[0].by = dot[0].ey
        dot[0].ex = loc.x
        dot[0].ey = loc.y
        this.drawFn(dot[0], num)
      }
    })
  }
}

// 平铺
class Pingpu extends Basic {
  constructor(width = RATIO, color = '#000') {
    super(width, color)
    this.name = 'pingpu'
    this.dom = selector(`#${this.name}`)
  }
  begin() {
    saveImageData(ctx.getImageData(0, 0, canvasWidth, canvasHeight))
    // 先保存画布状态，再改变画布状态
    ctx.save()
    ctx.lineWidth = this.width
    ctx.strokeStyle = this.color
    ctx.beginPath()
  }

  setCell(row, col) {
    return {
      cellWidth: canvasWidth / row,
      cellHeight: canvasHeight / col
    }
  }

  getBeginPosition(loc) {
    // 设置分隔
    var row = 4
    var col = 4
    var that = this

    var bx = 0
    var by = 0
    var ex = 0
    var ey = 0
    var cell = this.setCell(row, col)

    for (var i = 0; i < row; i++) {
      if (loc.bx - (cell.cellWidth * i) < 0) {
        bx = loc.bx - (cell.cellWidth * (i - 1))
        ex = loc.ex - (cell.cellWidth * (i - 1))
        break
      }
    }
    for (var i = 0; i < col; i++) {
      if (loc.by - (cell.cellHeight * i) < 0) {
        by = loc.by - (cell.cellHeight * (i - 1))
        ey = loc.ey - (cell.cellHeight * (i - 1))
        break
      }
    }
    return {
      // 起始点坐标
      x: bx,
      y: by,
      // 终止点坐标
      m: ex,
      n: ey,
    }
  }
  drawFn(bloc) {
    // 获取每格宽高
    var cell = this.setCell(4, 4)

    for (var i = 0; i < 8; i++) {
      for (var j = 0; j < 8; j++) {
        ctx.moveTo(bloc.x + cell.cellWidth * i, bloc.y + cell.cellHeight * j)
        ctx.lineTo(bloc.m + cell.cellWidth * i, bloc.n + cell.cellHeight * j)
        ctx.stroke()
      }
    }
  }

  bindEvent() {
    var dot = {
      bx: 0,
      by: 0,
      ex: 0,
      ey: 0,
    }

    var bloc
    canvas.addEventListener('touchstart', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      this.begin()
      this.drawing = true
      let loc = getTouchPosition(e)
      dot.ex = dot.bx = loc.x
      dot.ey = dot.by = loc.y
      // 获取初始点坐标
      bloc = this.getBeginPosition(dot)
    })
    canvas.addEventListener('touchmove', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      if (this.drawing) {
        let loc = getTouchPosition(e)
        dot.bx = dot.ex
        dot.by = dot.ey
        dot.ex = loc.x
        dot.ey = loc.y

        this.drawFn(this.getBeginPosition(dot))
      }
    })
  }
}

// 旋转对称
class Xuanzhuan2 extends Basic {
  constructor(width = RATIO, color = '#000') {
    super(width, color)
    this.name = 'xuanzhuan2'
    this.dom = selector(`#${this.name}`)
  }
  getNum() {
    var num = 6;
    var sel = document.getElementById("xzdc"); //定位id
    var index = sel.selectedIndex; // 选中索引
    var num = sel.options[index].value; // 选中值
    return num
  }
  begin() {
    saveImageData(ctx.getImageData(0, 0, canvasWidth, canvasHeight))
    // 先保存画布状态，再改变画布状态
    ctx.save()
    ctx.lineWidth = this.width
    ctx.strokeStyle = this.color
    ctx.beginPath()
  }

  drawFn(op, num) {
    var deg = Math.floor(360 / num);
    var that = this
    for (var i = 0, l = 360; i < l; i += deg) {
      this.drawRotate(i / 180 * Math.PI, function (ctx) {
        that.draw(op);
      });
    }
  }
  drawRotate(deg, fn, _ctx) {
    _ctx = _ctx || ctx
    _ctx.save();
    _ctx.translate(canvas.width / 2, canvas.height / 2);
    _ctx.rotate(deg);
    fn && fn(_ctx);
    _ctx.restore();
  }
  draw(option, _ctx) {
    _ctx = _ctx || ctx;
    _ctx.beginPath();
    _ctx.moveTo(option.bx - canvas.width / 2, option.by - canvas.height / 2);
    _ctx.lineTo(option.ex - canvas.width / 2, option.ey - canvas.height / 2);
    _ctx.stroke();
  }

  bindEvent() {
    var num = this.getNum()

    var sel = document.getElementById("xzdc")
    var that = this
    sel.onchange = function () {
      num = that.getNum()
    }

    var dot = [
      // 鼠标点
      {
        bx: 0,
        by: 0,
        ex: 0,
        ey: 0,
      },
      // 对称点
      {
        bx: 0,
        by: 0,
        ex: 0,
        ey: 0,
      }
    ]

    canvas.addEventListener('touchstart', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      this.begin()
      this.drawing = true
      let loc = getTouchPosition(e)
      dot[0].ex = dot[0].bx = loc.x
      dot[0].ey = dot[0].by = loc.y
      //
      let dloc = getTouchPositionD(e)
      dot[1].ex = dot[1].bx = dloc.x
      dot[1].ey = dot[1].by = dloc.y
    })
    canvas.addEventListener('touchmove', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      if (this.drawing) {
        let loc = getTouchPosition(e)
        let dloc = getTouchPositionD(e)
        dot[0].bx = dot[0].ex
        dot[0].by = dot[0].ey
        dot[0].ex = loc.x
        dot[0].ey = loc.y
        //
        dot[1].bx = dot[1].ex
        dot[1].by = dot[1].ey
        dot[1].ex = dloc.x
        dot[1].ey = dloc.y
        this.drawFn(dot[0], num)
        this.drawFn(dot[1], num)
      }
    })
  }
}

// 错位平铺
class Cuoweipingpu extends Basic {
  constructor(width = RATIO, color = '#000') {
    super(width, color)
    this.name = 'cwpp'
    this.dom = selector(`#${this.name}`)
  }
  begin() {
    saveImageData(ctx.getImageData(0, 0, canvasWidth, canvasHeight))
    // 先保存画布状态，再改变画布状态
    ctx.save()
    ctx.lineWidth = this.width
    ctx.strokeStyle = this.color
    ctx.beginPath()
  }

  setCell(row, col) {
    return {
      cellWidth: canvasWidth / row,
      cellHeight: canvasHeight / col
    }
  }

  getBeginPosition(loc) {
    // 设置分隔
    var row = 4
    var col = 4
    var that = this

    var bx = 0
    var by = 0
    var ex = 0
    var ey = 0
    var cell = this.setCell(row, col)

    for (var i = 0; i < row; i++) {
      if (loc.bx - (cell.cellWidth * i) < 0) {
        bx = loc.bx - (cell.cellWidth * (i - 1))
        ex = loc.ex - (cell.cellWidth * (i - 1))
        break
      }
    }
    for (var i = 0; i < col; i++) {
      if (loc.by - (cell.cellHeight * i) < 0) {
        by = loc.by - (cell.cellHeight * (i - 1))
        ey = loc.ey - (cell.cellHeight * (i - 1))
        break
      }
    }
    return {
      // 起始点坐标
      x: bx,
      y: by,
      // 终止点坐标
      m: ex,
      n: ey,
    }
  }
  drawFn(bloc) {
    // 获取每格宽高
    var cell = this.setCell(4, 4)

    for (var i = 0; i < 8; i++) {
      for (var j = 0; j < 8; j++) {
        if ((j + 2) % 2 == 0) {
          ctx.moveTo(bloc.x + cell.cellWidth * (i - 0.5), bloc.y + cell.cellHeight * j)
          ctx.lineTo(bloc.m + cell.cellWidth * (i - 0.5), bloc.n + cell.cellHeight * j)
          ctx.stroke()
        } else {
          ctx.moveTo(bloc.x + cell.cellWidth * i, bloc.y + cell.cellHeight * j)
          ctx.lineTo(bloc.m + cell.cellWidth * i, bloc.n + cell.cellHeight * j)
          ctx.stroke()
        }

      }
    }
  }

  bindEvent() {
    var dot = {
      bx: 0,
      by: 0,
      ex: 0,
      ey: 0,
    }

    var bloc
    canvas.addEventListener('touchstart', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      this.begin()
      this.drawing = true
      let loc = getTouchPosition(e)
      dot.ex = dot.bx = loc.x
      dot.ey = dot.by = loc.y
      // 获取初始点坐标
      bloc = this.getBeginPosition(dot)
    })
    canvas.addEventListener('touchmove', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      if (this.drawing) {
        let loc = getTouchPosition(e)
        dot.bx = dot.ex
        dot.by = dot.ey
        dot.ex = loc.x
        dot.ey = loc.y

        this.drawFn(this.getBeginPosition(dot))
      }
    })
  }
}

// 整合绘图工具
class Tool {
  constructor() {
    this.pencil = new Pencil(RATIO, '#000')
    this.eraser = new Eraser(RATIO * 10)
    this.clr = new Clear()
    this.zuoyou = new Zuoyou()
    this.xuanzhuan = new Xuanzhuan()
    this.xuanzhuan2 = new Xuanzhuan2()
    this.pingpu = new Pingpu()
    this.cwpp = new Cuoweipingpu()
    let allTools = [this.pencil, this.eraser, this.clr, this.zuoyou, this.xuanzhuan, this.pingpu, this.xuanzhuan2, this.cwpp]
    // 设置watcher 改变工具时改变工具的isSelected属性
    Object.defineProperty(this, 'selected', {
      set: function (value) {
        for (let item of allTools) {
          if (value == 'zxdc') {
            value = 'xuanzhuan'
          }
          if (value == 'xzdc') {
            value = 'xuanzhuan2'
          }
          if (item.name === value) {
            item.isSelect = true
            if (value == 'eraser') {
              item.dom.style.boxShadow = '2px 2px  15px #333'
            }
          } else {
            item.isSelect = false
            item.dom.style.boxShadow = '0px 0px  0px #fff'
          }
        }
      },
      get: function () {
        for (let item of allTools) {
          if (item.isSelect) {
            return item.name
          }
        }
      }
    })
  }
  bindEvent() {
    ctx.fillStyle = "#fff";
    ctx.fillRect(0, 0, canvasWidth, canvasHeight);

    var isEraser = false;
    this.selected = 'xuanzhuan'
    tool.addEventListener('click', (e) => {
      let target = e.target
      let name = target.getAttribute('id')
      if (name !== 'clr') {
        this.selected = name
      }
      lineWidth.range.value = this[name].width / RATIO
      if (isEraser) {
        this.selected = 'xuanzhuan'
      }
      if (name === 'eraser') {
        isEraser = !isEraser
        return false
      }
      if (name === 'clr') {
        ctx.fillStyle="#fff"
        ctx.fillRect(0,0,canvasWidth,canvasHeight)
        return false
      }
      palette.entrance.style.color = this[name].color
    })
    this.pencil.bindEvent()
    this.eraser.bindEvent()
    this.zuoyou.bindEvent()
    this.xuanzhuan.bindEvent()
    this.xuanzhuan2.bindEvent()
    this.pingpu.bindEvent()
    this.cwpp.bindEvent()
  }
}

//调色板
class Palette {
  constructor() {
    this.dom = selector("#Palette")
    this.entrance = selector("#toPalette")
    this.show = false
  }
  bindEvent() {
    this.dom.addEventListener('click', (e) => {
      const target = e.target
      if (target === this.entrance) {
        this.show = !this.show
        if (this.show) {
          this.dom.className = 'palette palette-show'
        } else {
          this.dom.className = 'palette'
        }
      } else if (target.className.indexOf('item') !== -1) {
        if (tools[tools.selected].name === 'eraser') {
          return false
        }
        const color = window.getComputedStyle(target, null).backgroundColor
        this.entrance.style.color = color
        tools[tools.selected].color = color
        this.dom.className = 'palette'
      }
    })
  }
}

//长度选择
class LineWidth {
  constructor() {
    this.dom = selector("#width")
    this.entrance = selector("#toWidth")
    this.range = selector("#lineWidth")
    this.show = false
  }
  bindEvent() {
    this.entrance.addEventListener('click', (e) => {
      this.show = !this.show
      if (this.show) {
        this.dom.className = 'width width-show'
      } else {
        this.dom.className = 'width'
      }
    })
    this.range.addEventListener('change', (e) => {
      const width = this.range.value
      tools[tools.selected].width = width * RATIO
      this.dom.className = 'width'
    })
  }
}

const tools = new Tool()
const palette = new Palette()
const lineWidth = new LineWidth()

lineWidth.bindEvent()
palette.bindEvent()
tools.bindEvent()

  ; (function (ctx) {
    selector("#cancel").addEventListener('click', () => {
      if (lastImageData.length < 1) return false
      ctx.putImageData(lastImageData[lastImageData.length - 1], 0, 0)
      lastImageData.pop()
    })
    selector("#saveImg").addEventListener('click', () => {
      handleSave();
      function handleSave() {
        //导出base64格式的图片数据
        var base64Data = canvas.toDataURL("image/jpeg", 0.5);
        //封装blob对象
        var blob = base64Data;
        //组装formdata
        var fd = new FormData();
        fd.append("fileName", "tupian0810.jpg");
        fd.append("fileData", blob);//fileData为自定义

        $.post({
          url: 'https://xcx.nanxuncn.cn/api/canvas/sketchpadaccs/base64',
          type: 'post',
          data: fd,
          contentType: false, // 注意这里应设为false
          processData: false,
          async: false,
          cache: false,
          success: function (data) {
            console.log(data)
            wx.miniProgram.navigateTo({
              url: '/pages/download/download?imgUrl=' + data,
              success: function () {
                console.log('success')
              },
              fail: function () {
                console.log('fail');
              },
              complete: function () {
                console.log('complete');
              }
            });
          },
          error: function (err) {
            console.log(err);
          }
        })
      };
    })
  })(ctx)